home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / DJGOS106.ARJ / SYMS.C < prev    next >
C/C++ Source or Header  |  1992-04-13  |  15KB  |  692 lines

  1. /* This is file SYMS.C */
  2. /*
  3. ** Copyright (C) 1991 DJ Delorie, 24 Kirsten Ave, Rochester NH 03867-2954
  4. **
  5. ** This file is distributed under the terms listed in the document
  6. ** "copying.dj", available from DJ Delorie at the address above.
  7. ** A copy of "copying.dj" should accompany this file; if not, a copy
  8. ** should be available from where this file was obtained.  This file
  9. ** may not be distributed without a verbatim copy of "copying.dj".
  10. **
  11. ** This file is distributed WITHOUT ANY WARRANTY; without even the implied
  12. ** warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  13. */
  14.  
  15. /* History:250,1 */
  16. #include <stdio.h>
  17. #include <fcntl.h>
  18. #include <string.h>
  19. #include <stdlib.h>
  20. #include <ctype.h>
  21. #include <io.h>
  22. #include "build.h"
  23. #include "types.h"
  24. #include "syms.h"
  25. #include "tss.h"
  26. #include "stab.h"
  27. #include "aout.h"
  28. #include "utils.h"
  29.  
  30. #if DEBUGGER
  31.  
  32. #define SYMADDR 0xa0000000
  33.  
  34. static word32 sym_brk=SYMADDR;
  35.  
  36. word32 salloc(word32 size)
  37. {
  38.   word32 r = sym_brk;
  39.   size = (size+3)&~3;
  40.   sym_brk +=size;
  41.   return r;
  42. }
  43.  
  44. symsput(word32 where, void *ptr, int size)
  45. {
  46.   memput(where, ptr, size);
  47. }
  48.  
  49. symsget(word32 where, void *ptr, int size)
  50. {
  51.   memget(where, ptr, size);
  52. }
  53.  
  54. typedef struct SYMTREE {
  55.   word32 me;
  56.   word32 nleft, nright, ndown;
  57.   word32 vleft, vright, vdown;
  58.   word32 val;
  59.   word32 type;
  60.   word32 name_len;
  61. } SYMTREE;
  62.  
  63. typedef struct FILENODE {
  64.   word32 me;
  65.   word32 next;
  66.   word32 line_list;
  67.   word32 first_addr, last_addr;
  68.   word32 name_len;
  69. } FILENODE;
  70.  
  71. typedef struct LINENODE {
  72.   word32 me;
  73.   word32 next;
  74.   word32 num;
  75.   word32 addr;
  76. } LINENODE;
  77.  
  78. static word32 symtree_root=0;
  79. static word32 file_list=0;
  80. static word32 nsyms=0;
  81.  
  82. static char tmps[256];
  83. static char tmps2[256];
  84.  
  85. static word32 symtree_add(word32 val, word32 type, char *name)
  86. {
  87.   SYMTREE s, sv, temp;
  88.   int cval;
  89.   int32 cval32;
  90.  
  91.   memset(&temp, 0, sizeof(temp));
  92.   temp.name_len = strlen(name) + 1;
  93.   temp.me = salloc(sizeof(temp)+temp.name_len);
  94.   temp.val = val;
  95.   temp.type = type;
  96.   symsput(temp.me, &temp, sizeof(temp));
  97.   symsput(temp.me+sizeof(temp), name, temp.name_len);
  98.  
  99.   if (symtree_root == 0)
  100.   {
  101.     symtree_root = temp.me;
  102.     return temp.me;
  103.   }
  104.   s.me = symtree_root;
  105.   while (1)
  106.   {
  107.     symsget(s.me, &s, sizeof(s));
  108.     symsget(s.me+sizeof(s), tmps, s.name_len);
  109.     cval = strcmp(name, tmps);
  110.     if ((cval == 0) &&
  111.         ( (s.val == 0)
  112.        || (val == 0)
  113.        || (s.val == val)))
  114.     {
  115.       if (val)
  116.       {
  117.         s.val = val;
  118.         s.type = type;
  119.         symsput(s.me, &s, sizeof(s));
  120.       }
  121.       return temp.me;
  122.     }
  123.     else if (cval == 0)
  124.     {
  125.       if (s.ndown == 0)
  126.       {
  127.         s.ndown = temp.me;
  128.         symsput(s.me, &s, sizeof(s));
  129.         break;
  130.       }
  131.       s.me = s.ndown;
  132.     }
  133.     else if (cval < 0)
  134.     {
  135.       if (s.nleft == 0)
  136.       {
  137.         s.nleft = temp.me;
  138.         symsput(s.me, &s, sizeof(s));
  139.         break;
  140.       }
  141.       s.me = s.nleft;
  142.     }
  143.     else
  144.     {
  145.       if (s.nright == 0)
  146.       {
  147.         s.nright = temp.me;
  148.         symsput(s.me, &s, sizeof(s));
  149.         break;
  150.       }
  151.       s.me = s.nright;
  152.     }
  153.   }
  154.   nsyms++;
  155.  
  156.   sv.me = symtree_root;
  157.   while (1)
  158.   {
  159.     symsget(sv.me, &sv, sizeof(sv));
  160.     if (sv.me == temp.me)
  161.       return temp.me;
  162.     cval32 = val - sv.val;
  163.     if (cval32 == 0)
  164.     {
  165.       if (sv.vdown == 0)
  166.       {
  167.         sv.vdown = temp.me;
  168.         symsput(sv.me, &sv, sizeof(sv));
  169.         break;
  170.       }
  171.       sv.me = sv.vdown;
  172.     }
  173.     else if (cval32 < 0)
  174.     {
  175.       if (sv.vleft == 0)
  176.       {
  177.         sv.vleft = temp.me;
  178.         symsput(sv.me, &sv, sizeof(sv));
  179.         break;
  180.       }
  181.       sv.me = sv.vleft;
  182.     }
  183.     else
  184.     {
  185.       if (sv.vright == 0)
  186.       {
  187.         sv.vright = temp.me;
  188.         symsput(sv.me, &sv, sizeof(sv));
  189.         break;
  190.       }
  191.       sv.me = sv.vright;
  192.     }
  193.   }
  194.   return temp.me;
  195. }
  196.  
  197. static symtree_print(word32 s, int byval, int level)
  198. {
  199.   SYMTREE tmp;
  200.   if (s == 0)
  201.     return;
  202.   symsget(s, &tmp, sizeof(tmp));
  203.   if (byval)
  204.     symtree_print(tmp.vleft, byval, level+1);
  205.   else
  206.     symtree_print(tmp.nleft, byval, level+1);
  207.  
  208.   symsget(tmp.me+sizeof(tmp), tmps, tmp.name_len);
  209.   printf("0x%08lx 0x%08lx %*s%s\n", tmp.val, tmp.type, level, "", tmps);
  210.  
  211.   if (byval)
  212.     symtree_print(tmp.vdown, byval, level);
  213.   else
  214.     symtree_print(tmp.ndown, byval, level);
  215.  
  216.   if (byval)
  217.     symtree_print(tmp.vright, byval, level+1);
  218.   else
  219.     symtree_print(tmp.nright, byval, level+1);
  220. }
  221.  
  222. void syms_list(v)
  223. {
  224.   symtree_print(symtree_root, v, 0);
  225. }
  226.  
  227. typedef struct SYM_ENTRY {
  228.   word32 string_off;
  229.   word8 type;
  230.   word8 other;
  231.   word16 desc;
  232.   word32 val;
  233. } SYM_ENTRY;
  234.  
  235. get_string(FILE *f, word32 where)
  236. {
  237.   char *cp;
  238.   if (where != ftell(f))
  239.     fseek(f, where, 0);
  240.   cp = tmps2;
  241.   do {
  242.     *cp++ = fgetc(f);
  243.   } while (cp[-1]);
  244. }
  245.  
  246. void syms_init(char *fname)
  247. {
  248.   GNU_AOUT header;
  249.   int fd, j, per, oldper=-1;
  250.   word32 nsyms, i;
  251.   FILE *sfd;
  252.   word32 sfd_base;
  253.   SYM_ENTRY sym;
  254.   char *strings, *cp;
  255.   word32 string_size;
  256.   word32 last_dot_o=0;
  257.   FILENODE filen;
  258.   LINENODE linen;
  259.  
  260.   filen.me = 0;
  261.   linen.me = 0;
  262.  
  263.   fd = open(fname, O_RDONLY | O_BINARY);
  264.   sfd = fopen(fname, "rb");
  265.  
  266.   read(fd, &header, sizeof(header));
  267.   if ((header.info & 0xffff) == 0x14c)
  268.   {
  269.     lseek(fd, 0xa8L, 0);
  270.     read(fd, &header, sizeof(header));
  271.     lseek(fd, 0xa8+sizeof(header) + header.tsize + header.dsize, 0);
  272.   }
  273.   else if (((header.info & 0xffff) == 0x10b) ||
  274.      ((header.info & 0xffff) == 0x0107))
  275.   {
  276.     lseek(fd, sizeof(header) + header.tsize + header.dsize
  277.       + header.txrel + header.dtrel, 0);
  278.   }
  279.   else
  280.   {
  281.     nsyms = 0;
  282.     return;
  283.   }
  284.  
  285.   printf("Reading symbols...   0%%");
  286.   fflush(stdout);
  287.  
  288.   nsyms = header.symsize / sizeof(SYM_ENTRY);
  289.  
  290.   fseek(sfd, tell(fd)+header.symsize, 0);
  291.   sfd_base = ftell(sfd);
  292.  
  293.   for (i=0; i<nsyms; i++)
  294.   {
  295.     if (nsyms > 1)
  296.       per = i*100L/(nsyms-1);
  297.     else
  298.       per = 100;
  299.     if (per != oldper)
  300.     {
  301.       printf("\b\b\b\b%3d%%", per);
  302.       fflush(stdout);
  303.       oldper = per;
  304.     }
  305.     read(fd, &sym, sizeof(sym));
  306.     if (sym.string_off)
  307.       get_string(sfd, sfd_base+sym.string_off);
  308.     switch (sym.type)
  309.     {
  310.       case N_TEXT:
  311.       case N_TEXT | N_EXT:
  312.         cp = tmps2;
  313.         cp += strlen(cp) - 2;
  314.         if (strcmp(cp, ".o") == 0)
  315.         {
  316.           last_dot_o = sym.val;
  317.           if (filen.me && (filen.last_addr == 0))
  318.           {
  319.             filen.last_addr = last_dot_o - 1;
  320.             symsput(filen.me, &filen, sizeof(filen));
  321.           }
  322.           break;
  323.         }
  324.         if (strcmp(cp, "d.") == 0) /* as in gcc_compiled. */
  325.           break;
  326.       case N_DATA:
  327.       case N_DATA | N_EXT:
  328.       case N_ABS:
  329.       case N_ABS | N_EXT:
  330.       case N_BSS:
  331.       case N_BSS | N_EXT:
  332.       case N_FN:
  333.       case N_SETV:
  334.       case N_SETV | N_EXT:
  335.       case N_SETA:
  336.       case N_SETA | N_EXT:
  337.       case N_SETT:
  338.       case N_SETT | N_EXT:
  339.       case N_SETD:
  340.       case N_SETD | N_EXT:
  341.       case N_SETB:
  342.       case N_SETB | N_EXT:
  343.       case N_INDR:
  344.       case N_INDR | N_EXT:
  345.         if (sym.string_off)
  346.           symtree_add(sym.val, sym.type, tmps2);
  347.         break;
  348.       case N_SO:
  349.         memset(&filen, 0, sizeof(FILENODE));
  350.         filen.name_len = strlen(tmps2)+1;
  351.         filen.me = salloc(sizeof(FILENODE)+filen.name_len);
  352.         symsput(filen.me+sizeof(filen), tmps2, filen.name_len);
  353.         filen.next = file_list;
  354.         file_list = filen.me;
  355.         filen.first_addr = last_dot_o;
  356.         symsput(filen.me, &filen, sizeof(filen));
  357.         break;
  358.       case N_SLINE:
  359.         memset(&linen, 0, sizeof(linen));
  360.         linen.me = salloc(sizeof(LINENODE));
  361.         linen.next = filen.line_list;
  362.         filen.line_list = linen.me;
  363.         linen.num = sym.desc;
  364.         linen.addr = sym.val;
  365.         symsput(linen.me, &linen, sizeof(linen));
  366.         symsput(filen.me, &filen, sizeof(filen));
  367.         break;
  368.     }
  369.   }
  370.   printf(" %ld symbol%s read\n", nsyms, nsyms==1 ? "" : "s");
  371.   return;
  372. }
  373.  
  374. #define Ofs(n) ((int)&(((TSS *)0)->n))
  375.  
  376. struct {
  377.   char *name;
  378.   int size;
  379.   int ofs;
  380.   } regs[] = {
  381.   "%eip", 4, Ofs(tss_eip),
  382.   "%eflags", 4, Ofs(tss_eflags),
  383.   "%eax", 4, Ofs(tss_eax),
  384.   "%ebx", 4, Ofs(tss_ebx),
  385.   "%ecx", 4, Ofs(tss_ecx),
  386.   "%edx", 4, Ofs(tss_edx),
  387.   "%esp", 4, Ofs(tss_esp),
  388.   "%ebp", 4, Ofs(tss_ebp),
  389.   "%esi", 4, Ofs(tss_esi),
  390.   "%edi", 4, Ofs(tss_edi),
  391.   "%ax", 2, Ofs(tss_eax),
  392.   "%bx", 2, Ofs(tss_ebx),
  393.   "%cx", 2, Ofs(tss_ecx),
  394.   "%dx", 2, Ofs(tss_edx),
  395.   "%ah", 1, Ofs(tss_eax)+1,
  396.   "%bh", 1, Ofs(tss_ebx)+1,
  397.   "%ch", 1, Ofs(tss_ecx)+1,
  398.   "%dh", 1, Ofs(tss_edx)+1,
  399.   "%al", 1, Ofs(tss_eax),
  400.   "%bl", 1, Ofs(tss_ebx),
  401.   "%cl", 1, Ofs(tss_ecx),
  402.   "%dl", 1, Ofs(tss_edx),
  403.   0, 0, 0
  404. };
  405.  
  406. int undefined_symbol=0;
  407.  
  408. word32 syms_name2val(char *name)
  409. {
  410.   SYMTREE s;
  411.   int cval, idx, sign=1, i;
  412.   word32 v;
  413.   char *cp;
  414.  
  415.   undefined_symbol = 0;
  416.  
  417.   idx = 0;
  418.   sscanf(name, "%s", name);
  419.  
  420.   if (name[0] == 0)
  421.     return 0;
  422.  
  423.   if (name[0] == '-')
  424.   {
  425.     sign = -1;
  426.     name++;
  427.   }
  428.   else if (name[0] == '+')
  429.   {
  430.     name++;
  431.   }
  432.   if (isdigit(name[0]))
  433.   {
  434.     if (sign == -1)
  435.       return -strtol(name, 0, 16);
  436.     return strtol(name, 0, 16);
  437.   }
  438.  
  439.   cp = strpbrk(name, "+-");
  440.   if (cp)
  441.     idx = cp-name;
  442.   else
  443.     idx = strlen(name);
  444.  
  445.   if (name[0] == '%') /* register */
  446.   {
  447.     for (i=0; regs[i].name; i++)
  448.       if (strncmp(name, regs[i].name, idx) == 0)
  449.       {
  450.         switch (regs[i].size)
  451.         {
  452.           case 1:
  453.             v = *(word8 *)((word8 *)tss_ptr + regs[i].ofs);
  454.             break;
  455.           case 2:
  456.             v = *(word16 *)((word8 *)tss_ptr + regs[i].ofs);
  457.             break;
  458.           case 4:
  459.             v = *(word32 *)((word8 *)tss_ptr + regs[i].ofs);
  460.             break;
  461.         }
  462.         return v + syms_name2val(name+idx);
  463.       }
  464.   }
  465.  
  466.   for (i=0; i<idx; i++)
  467.     if (name[i] == '#')
  468.     {
  469.       FILENODE f;
  470.       LINENODE l;
  471.       int lnum;
  472.       sscanf(name+i+1, "%d", &lnum);
  473.       for (f.me=file_list; f.me; f.me=f.next)
  474.       {
  475.         symsget(f.me, &f, sizeof(f));
  476.         symsget(f.me+sizeof(f), tmps, f.name_len);
  477.         if ((strncmp(name, tmps, i) == 0) && (tmps[i] == 0))
  478.         {
  479.           for (l.me=f.line_list; l.me; l.me=l.next)
  480.           {
  481.             symsget(l.me, &l, sizeof(l));
  482.             if (l.num == lnum)
  483.               return l.addr + syms_name2val(name+idx);
  484.           }
  485.           printf("undefined line number %.*s\n", idx, name);
  486.           undefined_symbol = 1;
  487.           return 0;
  488.         }
  489.       }
  490.       printf("Undefined file name %.*s\n", i, name);
  491.       undefined_symbol = 1;
  492.       return 0;
  493.     }
  494.  
  495.   s.me = symtree_root;
  496.   while (s.me)
  497.   {
  498.     symsget(s.me, &s, sizeof(s));
  499.     symsget(s.me+sizeof(s), tmps, s.name_len);
  500.     cval = strncmp(name, tmps, idx);
  501.     if ((cval == 0) && tmps[idx])
  502.       cval = -1;
  503.     if (cval == 0)
  504.       return s.val*sign + syms_name2val(name+idx);
  505.     else if (cval < 0)
  506.       s.me = s.nleft;
  507.     else
  508.       s.me = s.nright;
  509.   }
  510.   s.me = symtree_root;
  511.   while (s.me)
  512.   {
  513.     symsget(s.me, &s, sizeof(s));
  514.     symsget(s.me+sizeof(s), tmps, s.name_len);
  515.     if (tmps[0] == '_')
  516.       cval = strncmp(name, tmps+1, idx);
  517.     else
  518.       cval = '_' - tmps[0];
  519.     if ((cval == 0) && tmps[idx+1])
  520.       cval = -1;
  521.     if (cval == 0)
  522.       return s.val*sign + syms_name2val(name+idx);
  523.     else if (cval < 0)
  524.       s.me = s.nleft;
  525.     else
  526.       s.me = s.nright;
  527.   }
  528.   printf("Undefined symbol %.*s\n", idx, name);
  529.   undefined_symbol = 1;
  530.   return 0;
  531. }
  532.  
  533. static char noname_buf[11];
  534.  
  535. char *syms_val2name(word32 val, word32 *delta)
  536. {
  537.   SYMTREE s, lasts;
  538.  
  539.   if (delta)
  540.     *delta = 0;
  541.   lasts.me = 0;
  542.   s.me = symtree_root;
  543.   while (s.me)
  544.   {
  545.     symsget(s.me, &s, sizeof(s));
  546.     if (s.val <= val)
  547.       lasts.me = s.me;
  548.     if (val == s.val)
  549.     {
  550.       while (s.vdown)
  551.         symsget(s.vdown, &s, sizeof(s));
  552.       symsget(s.me+sizeof(s), tmps2, s.name_len);
  553.       return tmps2;
  554.     }
  555.     else if (val < s.val)
  556.       s.me = s.vleft;
  557.     else
  558.       s.me = s.vright;
  559.   }
  560.   if (lasts.me)
  561.   {
  562.     symsget(lasts.me, &lasts, sizeof(lasts));
  563.     while (lasts.vdown)
  564.       symsget(lasts.vdown, &lasts, sizeof(lasts));
  565.     symsget(lasts.me+sizeof(lasts), tmps2, lasts.name_len);
  566.     if (strcmp(tmps2, "_etext") == 0)
  567.       goto noname;
  568.     if (strcmp(tmps2, "_end") == 0)
  569.       goto noname;
  570.     if (delta)
  571.       *delta = val - lasts.val;
  572.     return tmps2;
  573.   }
  574. noname:
  575.   sprintf(noname_buf, "%#lx", val);
  576.   return noname_buf;
  577. }
  578.  
  579. char *syms_val2line(word32 val, int *lineret, int exact)
  580. {
  581.   FILENODE filen;
  582.   LINENODE linen, closest;
  583.   closest.me = 0;
  584.   for (filen.me = file_list; filen.me; filen.me=filen.next)
  585.   {
  586.     symsget(filen.me, &filen, sizeof(filen));
  587.     if ((val <= filen.last_addr) && (val >= filen.first_addr))
  588.     {
  589.       for (linen.me=filen.line_list; linen.me; linen.me = linen.next)
  590.       {
  591.         symsget(linen.me, &linen, sizeof(linen));
  592.         if (val == linen.addr)
  593.         {
  594.           *lineret = linen.num;
  595.           symsget(filen.me+sizeof(filen), tmps2, filen.name_len);
  596.           return tmps2;
  597.         }
  598.         if (val > linen.addr)
  599.         {
  600.           if (!closest.me)
  601.             closest.me = linen.me;
  602.           else if (closest.addr < linen.addr)
  603.             closest.me = linen.me;
  604.         }
  605.       }
  606.       if (closest.me && !exact)
  607.       {
  608.         symsget(closest.me, &closest, sizeof(closest));
  609.         *lineret = closest.num;
  610.         symsget(filen.me+sizeof(filen), tmps2, filen.name_len);
  611.         return tmps2;
  612.       }
  613.     }
  614.   }
  615.   return 0;
  616. }
  617.  
  618. static char type2char(type)
  619. {
  620.   switch (type)
  621.   {
  622.     case N_TEXT:
  623.       return 't';
  624.     case N_TEXT | N_EXT:
  625.       return 'T';
  626.     case N_DATA:
  627.       return 'd';
  628.     case N_DATA | N_EXT:
  629.       return 'D';
  630.     case N_BSS:
  631.       return 'b';
  632.     case N_BSS | N_EXT:
  633.       return 'B';
  634.     default:
  635.       return ' ';
  636.   }
  637. }
  638.  
  639. static int linecnt, quit_list;
  640.  
  641. static syms_listwild2(word32 s_pos, char *pattern)
  642. {
  643.   SYMTREE s;
  644.   char *name;
  645.   int lnum;
  646.   s.me = s_pos;
  647.   if ((s.me == 0) || quit_list)
  648.     return;
  649.   symsget(s.me, &s, sizeof(s));
  650.   syms_listwild2(s.vleft, pattern);
  651.   if (quit_list)
  652.     return;
  653.   symsget(s.me+sizeof(s), tmps, s.name_len);
  654.   if (wild(pattern, tmps))
  655.   {
  656.     if (++linecnt > 20)
  657.     {
  658.       printf("--- More ---");
  659.       switch (getch())
  660.       {
  661.         case ' ':
  662.           linecnt = 0;
  663.           break;
  664.         case 13:
  665.           linecnt--;
  666.           break;
  667.         case 'q':
  668.           quit_list = 1;
  669.           return;
  670.       }
  671.       printf("\r            \r");
  672.     }
  673.     printf("0x%08lx %c %s", s.val, type2char(s.type), tmps);
  674.     name = syms_val2line(s.val, &lnum, 0);
  675.     if (name)
  676.       printf(", line %d of %s", lnum, name);
  677.     mputchar('\n');
  678.   }
  679.   syms_listwild2(s.vdown, pattern);
  680.   if (quit_list)
  681.     return;
  682.   syms_listwild2(s.vright, pattern);
  683. }
  684.  
  685. void syms_listwild(char *pattern)
  686. {
  687.   quit_list = linecnt = 0;
  688.   syms_listwild2(symtree_root, pattern);
  689. }
  690.  
  691. #endif
  692.